/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mygameframework.sprite;

import com.mygameframework.isoengine.Direction;
import com.mygameframework.scenes.CommonScene;
import com.mygameframework.states.IState;
import com.mygameframework.states.StateMachine;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImageOp;
import java.util.LinkedList;
import java.util.Map;

/**
 *
 * @author bill
 */
public abstract class AbstractSprite extends BaseGameEntity {
    //TODO 子类应该: public static STATE_UP=1 ,STATE_LEFT=2,.....
//    protected int state;//位运算 & |
    protected IState<AbstractSprite> currentState;
    
    protected StateMachine<AbstractSprite> sm;
//    private Animation anim;   //改了,原是Map<IState,Animation>
    //<动画>
    protected Map<Integer,TileSetAnimation> anims;
    protected int currAnimationIdx; //当前动画的索引,anims.get()中使用
    
//    protected int currFrameIndex; //当前帧索引
//    protected long animTime;//time passed

    protected AffineTransform xform;
    
    protected double rotation; //旋转
    
    protected LinkedList collisionList;
    
    protected Point ptOldMap=new Point();//old Map point;
    protected Point ptMap=new Point();//Map point;
    protected Point ptUnitOffset=new Point();// for smooths slide from one tile to another
    protected Direction direct;
    protected CommonScene scene;
    
    
    // position (pixels)
    protected double x;
    protected double y;
    // velocity (pixels per millisecond)
    protected double dx;
    protected double dy;
    //frameWight frameHeight
    protected int w,h;
    
    protected Rectangle bound;
    /**
        Creates a new Sprite object with the specified Animation.
    */
    public AbstractSprite(Map<Integer,TileSetAnimation>  anims) {
        this.anims = anims;
        bound=new Rectangle();
    }

    public AbstractSprite() {
    }
    
    
    /**
        Updates this Sprite's Animation and its position based
        on the velocity.
    */
    @Override
    public void update(long elapsedTime) {
        currentState.execute(this, elapsedTime);
        updateSprite(elapsedTime);
        updateAnimation(elapsedTime);
    }
    protected  void updateAnimation(long elapsedTime){
        getAnimations().get(currAnimationIdx).update(elapsedTime);
    }
    /**
     * 负责更新,用户应从这方法更新sprite
     * 
     */
    public abstract void updateSprite(long elapsedTime);
    public  void paint(Graphics2D g2){
        TileSetAnimation animation=getAnimations().get(currAnimationIdx);
        byte tileIdx=animation.getCurrFrame().tileIdx;
        animation.tileSet.efficientPut(g2, 
                this.scene.getTileEngine().getScreenSpace(),
                (int)x+ptUnitOffset.x,  (int)y+ptUnitOffset.y, tileIdx);
        
    }
    public  void paint(Graphics2D g2,double x,double y){
    }
    public void paint(Graphics2D g2,BufferedImageOp filter){
    }
    /**
        Gets this Sprite's current x position.
    */
    public double getX() {
        return x;
    }

    /**
        Gets this Sprite's current y position.
    */
    public double getY() {
        return y;
    }

    /**
        Sets this Sprite's current x position.
    */
    public void setX(float x) {
        this.x = x;
    }

    /**
        Sets this Sprite's current y position.
    */
    public void setY(float y) {
        this.y = y;
    }
    public void updateBound(){
        TileSetAnimation currAnim= anims.get(currAnimationIdx);
//        if(w<=0 && currAnim!=null){
//            w=currAnim.getCurrFrame().getFrameWidth();
//        }
//        if(h<=0 && currAnim!=null){
//            h=currAnim.getCurrFrame().getFrameHeight();
//        }
//        bound.setRect(x, y, w, h);
        bound.setRect(currAnim.getCurrFrame().getDstExt());
        bound.translate((int)x,(int) y);
    }
    public Rectangle2D getBound() {
        updateBound();
        return bound;
    }
    public Map<Integer,TileSetAnimation> getAnimations(){
        return anims;
    }
    protected TileSetAnimation getCurrentAnimation(){
        return anims.get(currAnimationIdx);
    }
    protected void setCurrentAnimation(int idx){
        this.currAnimationIdx=idx;
        resetAnimation();
    }
    public void resetAnimation(){
//        this.animTime=0;
//        this.currFrameIndex=0;
        
    }

    public CommonScene getScene() {
        return scene;
    }

    public void setScene(CommonScene scene) {
        this.scene = scene;
    }
    
    public Point getOldMapPoint() {
        return ptOldMap;
    }

    public void setOldMapPoint(int xMap,int yMap) {
        this.ptOldMap.x=xMap;this.ptOldMap.y=yMap;
    }
    
    public void setMapPoint(int xMap,int yMap){
        this.ptMap.x=xMap;this.ptMap.y=yMap;
    }
    public Point getMapPoint(){
        return this.ptMap;
    }
    
    /**
        Gets this Sprite's current image.
    */
    public byte getTileIdx() {
        return getCurrentAnimation().getCurrTileIdx();
    }

    public Direction getDirection() {
        return direct;
    }

    public void setDirection(Direction direct) {
        this.direct = direct;
    }
    
    /**
        Gets this Sprite's width, based on the size of the
        current image.
    */
    public int getWidth() {
        return w;
    }

    /**
        Gets this Sprite's height, based on the size of the
        current image.
    */
    public int getHeight() {
        return h;
    }

    /**
        Gets the horizontal velocity of this Sprite in pixels
        per millisecond.
    */
    public double getVelocityX() {
        return dx;
    }

    /**
        Gets the vertical velocity of this Sprite in pixels
        per millisecond.
    */
    public double getVelocityY() {
        return dy;
    }

    /**
        Sets the horizontal velocity of this Sprite in pixels
        per millisecond.
    */
    public void setVelocityX(float dx) {
        this.dx = dx;
    }

    /**
        Sets the vertical velocity of this Sprite in pixels
        per millisecond.
    */
    public void setVelocityY(float dy) {
        this.dy = dy;
    }
    public boolean intersects(AbstractSprite other){
        return bound.intersects(other.getBound());
    }
    public boolean collidesWith(Sprite other){
        return (bound.contains(other.getBound()) || bound.intersects(other.getBound()));
    }
    
    public void move(Direction d){
        if(sm.getCurrentState()==SpriteState.SpriteState_IDLE){
            
            sm.changeState(SpriteState.SpriteState_StartMove);
        }
    }
    public void move(Direction[] d) {
        if (sm.getCurrentState() == SpriteState.SpriteState_IDLE) {

            sm.changeState(SpriteState.SpriteState_StartMove);
        }
    }
//    public final void setState(int attr){
//        state|=attr;
//    }
//    public final int getState(){
//        return state;
//    }
//    public final void resetState(int attr){
//        state &=~attr;
//    }
//    public final void clearState(){
//        state=0;
//    }
//    public final boolean hasState(int attr){
//        return (state&attr)!=0;
//    }
    public static void main(String[] args) {
        System.out.println(Integer.MAX_VALUE);
        System.out.println(Integer.MIN_VALUE);
    }
}
